import wx
from SensorPanel import SensorPanel
from BLPanel import BLPanel
from GHJPanel import GHJPanel
from VisualizationPanel import VisualizationPanel

NEW = 101
OPEN = 102
IMPORT = 103
EXPORT = 104
QUIT = 106
SAVE = 107
ANALYSE = 108

PREFERENCES = 201
SHOW_SENSORS = 202
SHOW_BONYLANDMARKS = 203
SHOW_3DMODEL = 204
ADDBONYLANDMARKS = 205
CHECKCOMPORTS = 206
WRITERAWDATA = 207
FASTACQUISITION = 208
EXPORTBLVECS = 209
REPLACEBONE = 210
STOREABS = 211

MINIMIZE = 301
MAXIMIZE = 302

ABOUT = 401

NOTEBOOK = 800

##  The main class of the Graphical User Interface with the notebook and menubar.
class GUI(wx.Frame):

    ##  The constructor of GUI. Builds the GUI.
    #   @param[in]  main    Main wx.App derived instance.
    #   @param[in]  *args   Automatically passed parameter.
    #   @param[in]  **kwds  Automatically passed parameter.
    def __init__(self, main, *args, **kwds) :
        kwds["style"] = wx.DEFAULT_FRAME_STYLE
        wx.Frame.__init__(self, *args, **kwds)
        ##  Main wx.App derived instance.
        self.main = main
        ##  wx.MenuBar()
        self.menubar = wx.MenuBar()
        self.SetMenuBar(self.menubar)

        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(NEW,"&New\tCtrl+N")
        wxglade_tmp_menu.Append(ANALYSE,"&Start Motion Analyser\tCtrl+M")
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(QUIT,"&Quit\tCtrl+Q")
        self.menubar.Append(wxglade_tmp_menu, "&File")

        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(SHOW_SENSORS,"Show &Sensors", kind=wx.ITEM_CHECK)
        wxglade_tmp_menu.Append(SHOW_BONYLANDMARKS,"Show &Bony &Landmarks", kind=wx.ITEM_CHECK)
        wxglade_tmp_menu.Append(SHOW_3DMODEL,"Show &3D &Model", kind=wx.ITEM_CHECK)
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(ADDBONYLANDMARKS,"&Add Bony Landmarks")
        wxglade_tmp_menu.Append(CHECKCOMPORTS,"&Check COM Ports")
        wxglade_tmp_menu.Append(PREFERENCES,"&Preferences")
        self.menubar.Append(wxglade_tmp_menu, "&Edit")
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(WRITERAWDATA,"&Write Raw Data", kind=wx.ITEM_CHECK)
        wxglade_tmp_menu.Append(FASTACQUISITION,"&Write Raw Data Fast", kind=wx.ITEM_CHECK)
        wxglade_tmp_menu.AppendSeparator()
        wxglade_tmp_menu.Append(EXPORTBLVECS,"Export BL vectors")
        wxglade_tmp_menu.Append(REPLACEBONE,"Replace Bone by Custom Model")
        wxglade_tmp_menu.Append(STOREABS,"Store absolute matrices")

        wxglade_tmp_menu = wx.Menu()
        wxglade_tmp_menu.Append(ABOUT,"&About")
        self.menubar.Append(wxglade_tmp_menu, "&Help")
        ##  wx.BoxSizer()
        self.sizer_1 = wx.BoxSizer(wx.VERTICAL)
        ##  wx.Notebook()
        self.notebook = wx.Notebook(self, NOTEBOOK, style=0)
        self.sizer_1.Add(self.notebook, 1, wx.EXPAND, 0)
        self.SetSizer(self.sizer_1)

        self.__SetProperties()
        self.__DoLayout()
        self.__BindEvents()

    def rightclick(self, event):
        print event
        
    ##  Sets properties for the panel.
    def __SetProperties(self):
        self.SetTitle("Flock of Birds Visualizer")
        self.SetSize((915, 760))
        self.SetBackgroundColour(wx.Colour(255, 255, 255))   
        self.SetIcon(wx.Icon("Images/icon.ico", wx.BITMAP_TYPE_ICO, 32, 32))

        self.menubar.Check(SHOW_SENSORS, True)
        self.menubar.Check(SHOW_BONYLANDMARKS, True)
        self.menubar.Check(SHOW_3DMODEL, True)
        self.menubar.Check(WRITERAWDATA, True)
        self.menubar.Check(FASTACQUISITION, False)

    ##  Sets layout for the panel.
    def __DoLayout(self):
        self.Layout()
        self.Centre()

    ##  Loads the notebook with its pages. Deletes the existing pages first.
    def LoadNotebook(self):
        self.notebook.DeleteAllPages()

        ## only add these pages when the fob is running
        if self.main.FOB_RUNNING:
            self.notebook.AddPage(SensorPanel(self.notebook, self.main.states.sensors), "Sensors")
            self.notebook.AddPage(BLPanel(self.notebook, self.main.states.bony_landmark), "Bony Landmarks")
            self.notebook.AddPage(GHJPanel(self.notebook, self.main.states.gh_cor), "GH-Joint")
        else:
            ## Disable or enable the comport check menu option according to if the fob is running
            self.menubar.GetMenu(1).FindItemByPosition(5).Enable(self.main.FOB_RUNNING)

        ## The visualization is always added, even when the fob is not running, the playback can still be used
        self.notebook.AddPage(VisualizationPanel(self.notebook, self.main.states.visualization), "Visualization")

        self.Layout()

    ##  Controls the events to be fired when tab changing takes place, this is needed when the tabs are used instead of the next and back buttons.
    #   The event handlers of those are called through this method, as they are needed for the checking.
    #
    #   This works by checking the difference between the current page and the newly selected page. Is one, then the next page or the page
    #   before is set depending on the sign of the difference (+ or -).
    #
    #   If the difference is larger than 1, the event handlers of the pages in between are triggered as well through the while loop.
    #   This makes sure that the checking for each page is done.
    def OnPageChanged(self, event):
        old = event.GetOldSelection()
        new = event.GetSelection()

        difference = new - old
        NAVIGATION_TO_NEXT = True

        if( old != -1 and difference == 1 ):
            self.notebook.GetPage(old).OnNext(None)
        if( old != -1 and difference <= -1 ):
            self.notebook.GetPage(old).OnBack(None,new)
        if( old != -1 and difference > 1 ):
            # Each OnNext method returns True when navigation to the following panel occurs.
            # If this does not occur, navigation to the next panel should not happen, so the loop will stop.
            while difference > 0 and NAVIGATION_TO_NEXT:
                NAVIGATION_TO_NEXT = self.notebook.GetPage(old).OnNext(None)
                old += 1
                difference = new - old


    ##  Checks whether or not "Show Sensors" in the menu is checked.
    #   @return[boolean]    True if SHOW_SENSORS is checked, else False.
    def IsSensorsChecked(self):
        return self.menubar.IsChecked(SHOW_SENSORS)

    ##  Returns whether or not "Show Bony Landmarks" in the menu is checked.
    def IsBonyLandmarksChecked(self):
        return self.menubar.IsChecked(SHOW_BONYLANDMARKS)

    ##  Returns whether or not "Show 3D Model" in the menu is checked.
    def Is3DModelChecked(self):
        return self.menubar.IsChecked(SHOW_3DMODEL)

    ##  Binds GUI menu items to methods in the main class.
    def __BindEvents(self):
        self.Bind(wx.EVT_MENU, self.main.OnNew, id=NEW)
        self.Bind(wx.EVT_MENU, self.main.OnStartAnalyser, id=ANALYSE)
        self.Bind(wx.EVT_MENU, self.main.OnAddBonyLandmark, id=ADDBONYLANDMARKS)
        self.Bind(wx.EVT_MENU, self.main.OnPreferences, id=PREFERENCES)
        self.Bind(wx.EVT_MENU, self.main.OnCheckCOMports, id=CHECKCOMPORTS)
        self.Bind(wx.EVT_MENU, self.main.OnToggleSensors, id=SHOW_SENSORS)
        self.Bind(wx.EVT_MENU, self.main.OnToggleBonyLandmarks, id=SHOW_BONYLANDMARKS)
        self.Bind(wx.EVT_MENU, self.main.OnToggle3DModel, id=SHOW_3DMODEL)
        self.Bind(wx.EVT_MENU, self.main.OnAbout, id=ABOUT)
        self.Bind(wx.EVT_MENU, self.main.OnDataWrite, id=WRITERAWDATA)
        self.Bind(wx.EVT_MENU, self.main.OnFastAcquisition, id=FASTACQUISITION)
        self.Bind(wx.EVT_MENU, self.main.OnExportBlVecs, id=EXPORTBLVECS)
        self.Bind(wx.EVT_MENU, self.main.OnReplaceBone, id=REPLACEBONE)
        self.Bind(wx.EVT_MENU, self.main.OnStoreAbsMatrices, id=STOREABS)        
        self.Bind(wx.EVT_CLOSE, self.main.OnQuit)
        self.Bind(wx.EVT_MENU, self.main.OnQuit, id=QUIT)
        self.Bind(wx.EVT_NOTEBOOK_PAGE_CHANGED, self.OnPageChanged, id=NOTEBOOK)
        
        #~ self.Unbind(wx.EVT_RIGHT_DOWN)
        #~ self.Bind(wx.EVT_RIGHT_DOWN, self.rightclick)